package net.oschina.simpleplus.erpc.api;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.springframework.context.ApplicationContext;

import net.sf.cglib.reflect.FastClass;

public class ERpcContainer {

	
	private Map<String, FastMethodInvoker> fastMethodInvokerCache = new HashMap<>();
	
	public ERpcContainer(ApplicationContext applicationContext){
		Map<String, Object> checkServiceBeanRepeatedCache = new HashMap<>();
		String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
		for (String beanName : beanDefinitionNames) {
			Object bean = applicationContext.getBean(beanName);
			Class<?>[] interfaces = bean.getClass().getInterfaces();
			if(interfaces != null && interfaces.length > 0){
				for (Class<?> class1 : interfaces) {
					Method[] methods = class1.getMethods();
					for (Method method : methods) {
						boolean find = false;
						if(method.isAnnotationPresent(ERpc.class)){
							String key = class1.getSimpleName()+"_"+method.getName();
							if(fastMethodInvokerCache.containsKey(key)){
								throw new RuntimeException("repeated method has same method!:"+class1.getName()+"_"+method.getName());
							}
							fastMethodInvokerCache.put(key, new FastMethodInvoker(bean, FastClass.create(bean.getClass()).getMethod(method)));
							find = true;
						}
						if(find){
							if(checkServiceBeanRepeatedCache.containsKey(class1.getSimpleName())){
								throw new RuntimeException("one interface has two or more implements class:"+class1.getName()
								+"["+checkServiceBeanRepeatedCache.get(class1.getSimpleName()).getClass().getName()+"],["+
										bean.getClass().getName()+"]");
							}
							checkServiceBeanRepeatedCache.put(class1.getSimpleName(), bean);
						}
					}
				}
			}
		}
	}
	
	
	public FastMethodInvoker find(String serviceName, String methodName){
		FastMethodInvoker fastMethodInvoker = fastMethodInvokerCache.get(serviceName+"_"+methodName);
		if(fastMethodInvoker == null){
			throw new RuntimeException("not exist className:["+serviceName+"],["+methodName+"]!");
		}
		return  fastMethodInvoker;
	}
}
